// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: linchuan

#include "coin2/exchange/bitstamp/api_util/auth_key.h"

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#include "coin2/base/time.h"
#include "coin2/exchange/base/api_util/api_signature.h"
#include "coin2/exchange/base/api_util/json_writer.h"

std::string BitstampBaseAuth::GetCurrTimeSeconds() {
  return std::to_string(GetCurrentTimestamp() / 1000000);
}

std::string BitstampBaseAuth::GetSignature(
    const std::string& secret_key,
    const std::string& api_str,
    const std::string& method,
    const std::string& host,
    const std::string& address,
    const std::string& content_type,
    const std::string& nonce,
    const std::string& timestamp,
    const std::string& request_body) {
  if (secret_key.empty()) {
    throw std::runtime_error("[bitstamp] secret key is empty");
  }
  std::string cre =
      api_str + method + host + address + content_type + nonce + timestamp + "v2" + request_body;
  return ApiSignatureUtil::GetSignatureByHexHmacSHA256(cre, secret_key);
}

std::vector<std::pair<std::string, std::string>> BitstampRestAuth::GetHeaderSet(
    const std::string& address,
    const std::string& method,
    const std::string& param) const {
  std::vector<std::pair<std::string, std::string>> out;
  std::string ts_str = GetCurrTimeSeconds();
  std::string api_str = "BITSTAMP " + key_.access_key();
  boost::uuids::uuid a_uuid = boost::uuids::random_generator()();
  std::string nonce = boost::uuids::to_string(a_uuid);
  std::string content_type = "";
  if (!param.empty()) {
    content_type = "application/x-www-form-urlencoded";
  }
  std::string signa = GetSignature(
      key_.secret_key(),
      api_str,
      method,
      host_,
      address,
      content_type,
      nonce,
      ts_str,
      param);
  out.push_back(std::make_pair("X-Auth", api_str));
  out.push_back(std::make_pair("X-Auth-Signature", signa));
  out.push_back(std::make_pair("X-Auth-Nonce", nonce));
  out.push_back(std::make_pair("X-Auth-Timestamp", ts_str));
  out.push_back(std::make_pair("X-Auth-Version", "v2"));
  if (!param.empty()) {
    out.push_back(std::make_pair("Content-Type", content_type));
  }
  return out;
}

AsioHttpContext* BitstampRestAuth::CreateRequestByPostWithSignature(
    const std::string& address,
    UrlParamsBuilder* builder) {
  std::string query_string = builder->ComputeQueryString();
  std::string post_body = builder->ComputePostBodyAsQueryString();
  std::string target = address;
  if (!query_string.empty()) {
    target += "?" + query_string;
  }
  return AsioHttpContext::NewPost(
      host_,
      port_,
      bind_ip_,
      target,
      GetHeaderSet(target, "POST", post_body),
      post_body);
}
